package jmine.tec.web.servlet.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import jmine.tec.web.servlet.BeanFactoryServletFilter;
import bancosys.tec.rtm.ExceptionContext;
import bancosys.tec.rtm.impl.RtmController;

/**
 * Filtro do RTM, usado para interceptar as exceções lançadas pelos outros filtros, deve ser registrado como primeiro filtro e filtrar
 * <code>/*</code>
 * 
 * @created May 6, 2008
 * @author Gustavo Almeida
 */
public class RtmFilter extends BeanFactoryServletFilter {
    private String rtmControllerName;

    /**
     * Le as configurações.
     * 
     * @param filterConfig configuração do filtro.
     */
    @Override
    public void initialize(FilterConfig filterConfig) {
        this.rtmControllerName = this.getParameter(filterConfig, "rtmController", "rtmController");
    }

    /**
     * Não faz nada.
     */
    public void destroy() {
        // vazio
    }

    /**
     * Executa o chain dentro de um <code>try/catch</code> para monitorar exceções.
     * 
     * @param request request.
     * @param response resposta.
     * @param chain chain.
     * @throws IOException se o chain lançar essa exceção.
     * @throws ServletException se o chain lançar essa exceção.
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ExceptionContext.initialize();
        try {
            chain.doFilter(request, response);
        } catch (RuntimeException e) {
            this.getController().monitor(e);
            throw e;
        } catch (IOException e) {
            this.getController().monitor(e);
            throw e;
        } catch (ServletException e) {
            Throwable exception;
            if (e.getRootCause() != null) {
                exception = e.getRootCause();
            } else {
                exception = e;
            }
            this.getController().monitor(exception);
            throw e;
        } finally {
            ExceptionContext.cleanup();
        }
    }

    /**
     * Devolve o controller do rtm.
     * 
     * @return RtmController.
     */
    private RtmController getController() {
        return this.getBean(this.rtmControllerName, RtmController.class);
    }
}
